#include "TiledInterpolator.h"
#include "ReadableImage.h"
#include "Color.h"

// Construct with edge modes.
TiledInterpolator::TiledInterpolator(EdgeMode horizontal_edge,
    EdgeMode vertical_edge)
    : horizontal_edge_(horizontal_edge),
      vertical_edge_(vertical_edge) {}

TiledInterpolator::~TiledInterpolator() {}

// Accesses a pixel in an image, applying edge behaviour settings.
Color TiledInterpolator::access(const ReadableImage& image, int i,
    int j) const {
  i = TiledInterpolator::constrain(i, image.height() - 1, vertical_edge_);
  j = TiledInterpolator::constrain(j, image.width() - 1, horizontal_edge_);
  return image.pixel(i, j);
}

// Wrap or hold based on specified behaviour.
int TiledInterpolator::constrain(int x, int max, EdgeMode mode) {
  if (mode == TiledInterpolator::LOOP) {
    // Loop around.
    x = x % (max + 1);
    // C++ mod isn't proper!
    if (x < 0) {
      x += (max + 1);
    }
  } else if (mode == TiledInterpolator::HOLD) {
    // Constrain to the range [0, max].
    if (x < 0) {
      x = 0;
    } else if (x > max) {
      x = max;
    }
  }
  return x;
}
